package com.linkwedo.saas.util.word;

/**
 * word �������
 * @author wucq
 *
 */
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.List;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

public class JavaToMSWordManager {
	// ��־
	private Logger logger = Logger.getLogger(JavaToMSWordManager.class);
	// word�ĵ�
	private Dispatch doc;
	// word���г������
	private ActiveXComponent word;
	// ����word�ĵ�����
	private Dispatch documents;
	// ѡ���ķ�Χ������
	private Dispatch selection;
	// �����˳��־
	private boolean saveOnExit = true;
	// ���б��
	private Dispatch tables = new Dispatch();
	// ����е�������
	private Dispatch columns;
	// ����е�ĳһ��
	private Dispatch column;
	// ����
	private static JavaToMSWordManager javaToMSWordManager = null;

	/**
	 * ����
	 * 
	 * @param visible
	 * @return
	 */
	public static JavaToMSWordManager getInstance(boolean visible) {
		if (javaToMSWordManager == null) {
			javaToMSWordManager = new JavaToMSWordManager(visible);
		}
		return javaToMSWordManager;
	}

	/**
	 * ��wordʱͬʱҪ�򿪵��ĵ�����ָ��ʱ���½�һ��հ��ĵ� (fasle ֻ���ĵ���true ʱ���ĵ���ʱ�ɿ����ĵ����ݵ�д��)
	 * 
	 * @param visible
	 *            (fasle ֻ���ĵ���true ʱ���ĵ���ʱ�ɿ����ĵ����ݵ�д��)
	 * @throws JavaToWordException
	 */
	private JavaToMSWordManager(boolean visible) {
		try {
			if (word == null) {
				word = new ActiveXComponent("Word.Application");
				word.setProperty("Visible", new Variant(visible));
				logger
						.debug("JavaToMSWordManager.JavaToMSWordManager(boolean visible:"+visible+"):ʵ�� Word �ɹ�!");
			}
			if (documents == null) {
				documents = word.getProperty("Documents").toDispatch();
				logger
						.debug("JavaToMSWordManager.JavaToMSWordManager(boolean visible:"+visible+"):��ȡ Word Documents �ĵ����Գɹ���");
			}
		} catch (Exception e) {
			logger
					.error("JavaToMSWordManager.JavaToMSWordManager(boolean visible:"+visible+"):ʵ���?������Ϣ��"
							+ e.getMessage());
		}
	}

	/**
	 * ����һ���µ�word�ĵ�
	 * 
	 * @throws JavaToWordException
	 */
	public void createNewDocument() {
		try {
			doc = Dispatch.get(word, "Documents").toDispatch();
			doc = Dispatch.call(doc, "Add").toDispatch();
			logger
					.debug("JavaToMSWordManager.createNewDocument():����һ���� Word �ĵ��ɹ���");
		} catch (Exception e) {
			logger
					.error("JavaToMSWordManager.createNewDocument():����һ���µ� word �ĵ���?������Ϣ��"
							+ e.getMessage());
		}
	}

	/**
	 * ��һ���Ѵ��ڵ��ĵ�
	 * 
	 * @param docPath
	 */
	public void openDocument(String docPath) {

		try {
			doc = Dispatch.call(documents, "Open", docPath).toDispatch();
			logger
					.debug("JavaToMSWordManager.openDocument(String docPath):��һ���Ѿ����ڵ��ĵ�!");
		} catch (Exception e) {
			logger
					.error("JavaToMSWordManager.openDocument(String docPath):��һ���Ѿ����ڵ��ĵ���?������Ϣ��"
							+ e.getMessage());
		}

	}

	/**
	 * �ر��ĵ�
	 * 
	 * @param val
	 *            0�������޸� -1 �����޸� -2 ��ʾ�Ƿ񱣴��޸�
	 */
	public void closeDocument(int val) {
		try {
			Dispatch.call(doc, "Close", new Variant(val));
			doc = null;
			logger.debug("JavaToMSWordManager,closeDocument(" + val
					+ "):�ر� Word �ĵ���");
		} catch (Exception e) {
			// TODO: handle exception
			logger.error("JavaToMSWordManager,closeDocument(" + val
					+ "):�ر� Word �ĵ���?������Ϣ��" + e.getMessage());
		}
	}

	/**
	 * �رյ�ǰword�ĵ�
	 * 
	 */
	public void closeDocument() {
		try {
			if (doc != null) {
				Dispatch.call(doc, "Save");
				Variant a = Dispatch
						.call(doc, "Close", new Variant(saveOnExit));
				doc = null;
				logger
						.debug("JavaToMSWordManager.closeDocument():�ر� Word �ĵ��ɹ���");
			}
		} catch (Exception e) {
			// TODO: handle exception
			logger
					.error("JavaToMSWordManager.closeDocument():�ر� Word �ĵ���?������Ϣ��"
							+ e.getMessage());
		}
	}

	/**
	 * �ļ���������Ϊ
	 * 
	 * @param savePath
	 *            ��������Ϊ·��
	 */
	public void save(String savePath) {
		try {
			Dispatch.call(Dispatch.call(word, "WordBasic").getDispatch(),
					"FileSaveAs", savePath);
			logger.debug("JavaToMSWordManager.save(" + savePath
					+ "):�ļ���������Ϊ����ɹ���");
		} catch (Exception e) {
			// TODO: handle exception
			logger.error("JavaToMSWordManager.save(" + savePath
					+ "):�ļ���������Ϊ�����?������Ϣ��" + e.getMessage());
		}
	}

	/**
	 * �ڵ�ǰ���������ı�
	 * 
	 * @param imagePath
	 *            ͼƬ·��
	 */
	public void insertText(String content) {
		try {

			Dispatch wordContent = Dispatch.get(doc, "content").toDispatch();
			wordContent.put(selection, "Text", content);
			logger.debug("JavaToMSWordManager.insertText(" + content
					+ ") : Word �ĵ���ǰ���������ı��ɹ���");
		} catch (Exception e) {
			logger.error("JavaToMSWordManager.insertText(" + content
					+ ") : Word �ĵ���ǰ���������ı���?������Ϣ��" + e.getMessage());
		}
	}

	/**
	 * �ڵ�ǰ��������ͼƬ
	 * 
	 * @param imagePath
	 *            ͼƬ·��
	 */
	public void insertImage(String imagePath) {
		try {
			Dispatch.call(Dispatch.get(selection, "InLineShapes").toDispatch(),
					"AddPicture", imagePath);
			logger.debug("JavaToMSWordManager.insertImage(" + imagePath
					+ "): Word �ĵ���ǰ��������ͼƬ�ɹ���");
		} catch (Exception e) {
			logger.error("JavaToMSWordManager.insertImage(" + imagePath
					+ "): Word �ĵ���ǰ��������ͼƬ��?������Ϣ��" + e.getMessage());
		}
	}

	/**
	 * ������Ƶ��ļ�ĩβ
	 */
	public void moveEnd() {
		try {
			if (selection == null)
				selection = Dispatch.get(word, "Selection").toDispatch();
			Dispatch.call(selection, "EndKey", new Variant(6));
			logger.debug("JavaToMSWordManager.moveEnd():����Ƶ��ļ�ĩβ");
		} catch (Exception e) {
			logger.error("JavaToMSWordManager.moveEnd():����Ƶ��ļ�ĩβ��?������Ϣ��"
					+ e.getMessage());
		}
	}

	/**
	 * �������
	 * 
	 * @param numCols
	 *            �����������
	 * @param numRows
	 *            �����������
	 */
	public void createTable(int numCols, int numRows) {
		try {
			tables = Dispatch.get(doc, "Tables").toDispatch();

			Dispatch range = Dispatch.get(selection, "Range").toDispatch();
			Dispatch newTable = Dispatch.call(tables, "Add", range,
					new Variant(numRows), new Variant(numCols)).toDispatch();
			Dispatch.put(selection, "Style", "�����");
			Dispatch.call(selection, "MoveRight");
			logger.debug("JavaToMSWordManager.createTable(numCols:" + numCols
					+ ",numRows:" + numRows + "): �������ɹ���");
		} catch (Exception e) {
			logger.error("JavaToMSWordManager.createTable(numCols:" + numCols
					+ ",numRows:" + numRows + "): ��������?������Ϣ��"
					+ e.getMessage());
		}
	}

	/**
	 * ���õ�ǰ���ָ���е��п�
	 * 
	 * @param columnWidth
	 *            �еĿ��
	 * @param columnIndex
	 *            �е���
	 * @throws ���������ı����ʹ��
	 */
	public void setColumnWidth(float columnWidth, int columnIndex) {
		try {
			if (columnWidth < 11) {
				columnWidth = 120;
			}
			if (columns == null || column == null) {
				this.getColumns();
				this.getColumn(columnIndex);
			}
			Dispatch.put(column, "Width", new Variant(columnWidth));
			logger.debug("JavaToMSWordManager.setColumnWidth(columnWidth:"
					+ columnWidth + ",columnIndex:" + columnIndex
					+ "):���õ�ǰ���ָ���е��п�");
		} catch (Exception e) {
			logger.error("JavaToMSWordManager.setColumnWidth(columnWidth:"
					+ columnWidth + ",columnIndex:" + columnIndex
					+ "):���õ�ǰ���ָ���е��п��?������Ϣ��" + e.getMessage());
		}
	}

	/**
	 * �õ���ǰ�������е��� ��Ҫ�ҵ�Dispatch����,�����Variant(1)����һ��Ҫ��ɱ�
	 * 
	 * @return
	 */
	public Dispatch getColumns() {
		try {
			Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
			Dispatch table = Dispatch.call(tables, "Item", new Variant(1))
					.toDispatch();
			logger.debug("JavaToMSWordManager.getColumns():�õ���ǰ�������е���!");
			return this.columns = Dispatch.get(table, "Columns").toDispatch();
		} catch (Exception e) {
			logger.error("JavaToMSWordManager.getColumns():�õ���ǰ�������е��г�?������Ϣ��"
					+ e.getMessage());
		}
		return null;
	}

	/**
	 * �õ���ǰ����ĳһ��
	 * 
	 * @param columnIndex
	 *            ����е�����
	 * @return
	 */
	public Dispatch getColumn(int columnIndex) {
		try {
			if (columns == null)
				this.getColumns();
			logger.info("JavaToMSWordManager.getColumn(columnIndex:"
					+ columnIndex + "):�õ���ǰ����ĳһ��!");
			return this.column = Dispatch.call(columns, "Item",
					new Variant(columnIndex)).toDispatch();
		} catch (Exception e) {
			logger.error("JavaToMSWordManager.getColumn(columnIndex:"
					+ columnIndex + "):�õ���ǰ����ĳһ�г�?������Ϣ:" + e.getMessage());
		}
		return null;

	}

	/**
	 * �ϲ���Ԫ��
	 * 
	 * @param tableIndex
	 *            �ڼ��ű�(����)
	 * @param fstCellRowIdx
	 *            ��ʼ����
	 * @param fstCellColIdx
	 *            ��ʼ����
	 * @param secCellRowIdx
	 *            ��������
	 * @param secCellColIdx
	 *            ��������
	 */
	public void mergeCell(int tableIndex, int fstCellRowIdx, int fstCellColIdx,
			int secCellRowIdx, int secCellColIdx) {
		try {
			// ���б��
			Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
			// Ҫ���ı��
			Dispatch table = Dispatch.call(tables, "Item",
					new Variant(tableIndex)).toDispatch();
			Dispatch fstCell = Dispatch.call(table, "Cell",
					new Variant(fstCellRowIdx), new Variant(fstCellColIdx))
					.toDispatch();
			Dispatch secCell = Dispatch.call(table, "Cell",
					new Variant(secCellRowIdx), new Variant(secCellColIdx))
					.toDispatch();
			Dispatch.call(fstCell, "Merge", secCell);
			logger.debug("JavaToMSWordManager.mergeCell(tableIndex:"
					+ tableIndex + ", fstCellRowIdx:" + fstCellRowIdx
					+ ",  fstCellColIdx:" + fstCellColIdx + ",  secCellRowIdx:"
					+ secCellRowIdx + ", secCellColIdx:" + secCellColIdx
					+ ")���ϲ���Ԫ��ɹ�!");
		} catch (Exception e) {
			logger.error("JavaToMSWordManager.mergeCell(tableIndex:"
					+ tableIndex + ", fstCellRowIdx:" + fstCellRowIdx
					+ ",  fstCellColIdx:" + fstCellColIdx + ",  secCellRowIdx:"
					+ secCellRowIdx + ", secCellColIdx:" + secCellColIdx
					+ ")���ϲ���Ԫ���?������Ϣ��" + e.getMessage());
		}
	}

	/**
	 * �ĵ��еı����
	 * 
	 * @return
	 */
	public int tableCount() {
		try {
			// ���б��
			Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
			int count = Dispatch.get(tables, "Count").toInt();
			logger.debug("JavaToMSWordManager.tableCount() �ĵ��еı����:" + count);
			return count;
		} catch (Exception e) {
			logger.error("JavaToMSWordManager.tableCount():�ĵ��еı�����ȡ��?������Ϣ:"
					+ e.getMessage());
		}
		return 0;

	}

	/**
	 * ��ָ���ĵ�Ԫ������д���
	 * 
	 * @param tableIndex
	 *            �ڼ��ű�
	 * @param cellRowIdx
	 *            �ڼ���
	 * @param cellColIdx
	 *            �ڼ���
	 * @param txt
	 *            �������
	 * @param alignment
	 *            ���뷽ʽ:1Ϊ����,0�����
	 */
	public void putTxtToCell(int tableIndex, int cellRowIdx, int cellColIdx,
			String txt, int alignment) {
		try {
			// ���б��
			Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
			// Ҫ���ı��
			Dispatch table = Dispatch.call(tables, "Item",
					new Variant(tableIndex)).toDispatch();

			Dispatch cell = Dispatch.call(table, "Cell",
					new Variant(cellRowIdx), new Variant(cellColIdx))
					.toDispatch();
			Dispatch.call(cell, "Select");
			Dispatch paragraphFormat = Dispatch.get(selection,
					"ParagraphFormat").toDispatch();
			if (alignment == 1)
				Dispatch.put(paragraphFormat, "Alignment", "1");
			Dispatch.put(selection, "Text", txt);
			logger.info("JavaToMSWordManager.putTxtToCell(tableIndex:"
					+ tableIndex + ", cellRowIdx:" + cellRowIdx
					+ ", cellColIdx:" + cellColIdx + ", txt:" + cellColIdx
					+ ", alignment:" + alignment + ")����ָ���ĵ�Ԫ������д��ݣ�");
		} catch (Exception e) {
			logger.error("JavaToMSWordManager.putTxtToCell(tableIndex:"
					+ tableIndex + ", cellRowIdx:" + cellRowIdx
					+ ", cellColIdx:" + cellColIdx + ", txt:" + cellColIdx
					+ ", alignment:" + alignment + ")����ָ���ĵ�Ԫ������д��ݳ�?������Ϣ��"
					+ e.getMessage());
		}
	}

	/**
	 * �س����в���
	 */
	public void insertNewParagraph() {
		try {
			Dispatch.call(selection, "EndKey", "5");
			Dispatch.call(selection, "TypeParagraph");
			logger.debug("JavaToMSWordManager.insertNewParagraph():�س����в���");
		} catch (Exception e) {
			logger
					.error("JavaToMSWordManager.insertNewParagraph():�س����в����?�����Ϣ��"
							+ e.getMessage());
		}
	}

	/**
	 * ��ѡ��ѡ�������趨Ϊ�滻�ı�
	 * 
	 * @param toFindText
	 *            �����ַ�
	 * @param newText
	 *            Ҫ�滻������
	 * @return
	 */
	public boolean replaceText(String toFindText, String newText) {
		// /if (!find(toFindText))
		// return false;
		try {
			Dispatch.put(selection, "Text", newText);
			logger.debug("JavaToMSWordManager.replaceText(toFindText:"
					+ toFindText + ", newText:" + newText + "):��ѡ��ѡ�������趨Ϊ�滻�ı�");
		} catch (Exception e) {
			// TODO: handle exception
			logger.debug("JavaToMSWordManager.replaceText(toFindText:"
					+ toFindText + ", newText:" + newText
					+ "):��ѡ��ѡ�������趨Ϊ�滻�ı���?������Ϣ��" + e.getMessage());
		}
		return true;
	}

	/**
	 * �滻�ı�
	 * 
	 * @param newText
	 * @return
	 */
	public boolean replaceText(String newText) {
		try {
			Dispatch.put(selection, "Text", newText);
			logger.debug("JavaToMSWordManager.replaceText(newText:" + newText
					+ "):�滻�ı�");
		} catch (Exception e) {
			// TODO: handle exception
			logger.error("JavaToMSWordManager.replaceText(newText:" + newText
					+ "):�滻�ı���?������Ϣ��" + e.getMessage());
		}
		return true;
	}

	/**
	 * ����ָ��Ŀ¼·���µ��ļ�
	 * 
	 * @param filepathdir
	 *            ָ��Ŀ¼
	 * @param filename
	 *            �ļ���
	 * @throws FileNotFoundException
	 * @throws JavaToWordException
	 */
	public void writeFile(String filepathdir, String filename)
			throws FileNotFoundException {
		try {
			java.io.File aFile = new java.io.File(filepathdir);
			if (!aFile.exists()) {
				aFile.mkdirs();
			}
			PrintWriter printwriter = new PrintWriter(new FileOutputStream(
					filepathdir + "/" + filename));
			printwriter.close();
			logger.debug("JavaToMSWordManager.writeFile(filepathdir:"
					+ filepathdir + ",  filename:" + filename + "):����ָ��Ŀ¼·���µ�"
					+ filename + "�ļ��ɹ���");
		} catch (Exception e) {
			// TODO: handle exception
			logger.error("JavaToMSWordManager.writeFile(filepathdir:"
					+ filepathdir + ",  filename:" + filename + "):����ָ��Ŀ¼·���µ�"
					+ filename + "�ļ���?������Ϣ��" + e.getMessage());
		}
	}

	/**
	 * �ϲ�WORD�ĵ�,��һ��ΪҪ�ϲ����ĵ�
	 * 
	 * @param fileList
	 * @param savepaths
	 */
	public void uniteDoc(List fileList, String savepaths) {

		if (fileList.size() == 0 || fileList == null) {
			logger
					.debug("JavaToMSWordManager.uniteDoc(fileList.size() == 0 || fileList == null,  savepaths:"
							+ savepaths + "):���ĵ��ɺϲ�!");
			return;
		}

		try {

			// ���documents����
			Object docs = word.getProperty("Documents").toDispatch();
			// �򿪵�һ���ļ�
			Dispatch doc = Dispatch.invoke(

			(Dispatch) docs,

			"Open",

			Dispatch.Method,

			new Object[] { (String) fileList.get(0),

			new Variant(false), new Variant(true) },

			new int[3]).toDispatch();

			// ׷���ļ�

			for (int i = 1; i < fileList.size(); i++) {

				Dispatch.call(word.getProperty("Selection").toDispatch(),
						"HomeKey", new Variant(6));

				Dispatch.invoke(word.getProperty("Selection").toDispatch(),

				"insertFile", Dispatch.Method, new Object[] {

				(String) fileList.get(i), "",

				new Variant(false), new Variant(false),

				new Variant(false) }, new int[3]);

			}
			logger
					.debug("JavaToMSWordManager.uniteDoc(fileList.size():"
							+ fileList.size() + ",  savepaths:" + savepaths
							+ "):�ϲ��ɹ���");
		} catch (Exception e) {

			logger.error("JavaToMSWordManager.uniteDoc(fileList.size():"
					+ fileList.size() + ",  savepaths:" + savepaths
					+ "):�ϲ��ĵ���?������Ϣ��" + e.getMessage());

		}
	}
	/**
	 * Web response �����ĵ�
	 * @param response 
	 * @param expfilepath ��Ҫ�����ļ��ķ�����·��
	 * @param expfilename ��Ҫ�����ļ��ڿͻ��˵��ļ���
	 */
	public void respsonseExpWord(HttpServletResponse response,String expfilepath,String expfilename){
		try {
			File file = new File(expfilepath);
			FileInputStream is = new FileInputStream(file);
			BufferedInputStream bis = null;

			BufferedOutputStream bos = null;

			// ���汾���ļ���
			int fileSize = (int) file.length();
			String filename = URLEncoder.encode(expfilename, "UTF-8"); //�����ļ���(����)ת��   
			// ���������ļ�ʹ�õı�ͷ��
			response.reset();
			response.setContentType("application/msword");
			response.setHeader("Content-Disposition", "attachment; filename="
					+ filename);
			response.setContentLength(fileSize);
			// �õ���Ӧ����������������ͻ��������������
			ServletOutputStream sos = response.getOutputStream();
			bis = new BufferedInputStream(is);

			bos = new BufferedOutputStream(response.getOutputStream());

			byte[] buff = new byte[2048];

			int bytesRead;

			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {

				bos.write(buff, 0, bytesRead);
			}

			bos.flush();
			bos.close();
			bis.close();
//			file.delete();//�����ĵ���ɾ��ԭ�ļ�
			logger.debug("JavaToMSWordManager.respsonseExpWord(response,expfilepath:"+expfilepath+",  expfilename:"+expfilename+"):response Web ��Ӧ�����ĵ��ɹ���");
		} catch (Exception e) {
			// TODO: handle exception
			logger.error("JavaToMSWordManager.respsonseExpWord(response,expfilepath:"+expfilepath+",  expfilename:"+expfilename+"):response Web ��Ӧ�����ĵ���?������Ϣ��"+e.getMessage());
		}
	}
}